#pragma once

#include <iostream>
#include <vector>
#include <string>
#include <queue>
#include <unistd.h>
#include "Thread.hpp"
#include "LockGuard.hpp"
#include "Log.hpp"
#include "Task.hpp"

using namespace ns_log;
static const int defaultnum = 5;

// 线程数据
class ThreadData
{
public:
    ThreadData(const std::string &name) : threadname(name)
    {
    }
    ~ThreadData()
    {
    }

public:
    std::string threadname;
};

template <class T>
class ThreadPool
{
private:
    ThreadPool(int num = defaultnum) : _thread_num(num)
    {
        pthread_mutex_init(&_mutex, nullptr);
        pthread_cond_init(&_cond, nullptr);
        // 创建指定个数的线程
        for (int i = 0; i < _thread_num; i++)
        {
            std::string threadname = "thread-";
            threadname += std::to_string(i + 1);

            ThreadData td(threadname);
            // 创建
            // Thread<ThreadData> t(threadname, std::bind(&ThreadPool<T>::ThreadRun, this, std::placeholders::_1), td);
            // _threads.push_back(t);
            // 两种写法都可行，这种写法可以减少拷贝
            _threads.emplace_back(threadname, std::bind(&ThreadPool<T>::ThreadRun, this, std::placeholders::_1), td);
            LOG(INFO) << td.threadname << " is created..." << "\n";
        }
    }
    ThreadPool(const ThreadPool<T> &tp) = delete;
    const ThreadPool<T> &operator=(const ThreadPool<T>) = delete;

public:
    static ThreadPool<T> *GetInstance()  // 创建单例
    {
        if (instance == nullptr)
        {
            LockGuard lockguard(&sig_lock); // 在多线程中存在线程安全问题，需要注意加锁
            if (instance == nullptr)
            {
                LOG(INFO) << "创建单例成功....\n";
                instance = new ThreadPool<T>();
            }
        }

        return instance;
    }
    // 启动线程池
    bool Start()
    {
        for (auto &thread : _threads)
        {
            thread.Start();
            LOG(INFO) << thread.ThreadName() << " is running..." << "\n";
        }
        return true;
    }
    void ThreadWait() // 等待
    {
        pthread_cond_wait(&_cond, &_mutex);
    }
    void ThreadWakeup() // 唤醒
    {
        pthread_cond_signal(&_cond);
    }
    // 执行任务
    void ThreadRun(ThreadData &td)
    {
        while (true)
        {
            T t;
            // 取任务
            {
                // 加锁
                LockGuard lockguard(&_mutex);
                while (_q.empty())
                {
                    // 没有任务时就等待
                    ThreadWait();
                }
                t = _q.front();
                _q.pop();
            }
            // 处理任务
            t();
            LOG(DEBUG) << td.threadname << " handler task " << t.PrintTask() << " ,result is: " << t.PrintResult() << "\n";
        }
    }
    // 添加任务
    void Push(const T &in)
    {
        // 加锁
        LockGuard lockguard(&_mutex);
        // 添加
        _q.push(in);
        // 唤醒
        ThreadWakeup();
    }
    // 等待线程
    void Wait()
    {
        for (auto &thread : _threads)
        {
            thread.Join();
        }
    }
    ~ThreadPool()
    {
        pthread_mutex_destroy(&_mutex);
        pthread_cond_destroy(&_cond);
    }

private:
    std::queue<T> _q;                         // 任务队列
    std::vector<Thread<ThreadData>> _threads; // 线程池
    int _thread_num;                          // 线程个数
    pthread_mutex_t _mutex;                   // 锁
    pthread_cond_t _cond;                     // 条件变量

    static ThreadPool<T> *instance;
    static pthread_mutex_t sig_lock;
};

template <class T>
ThreadPool<T> *ThreadPool<T>::instance = nullptr;
template <class T>
pthread_mutex_t ThreadPool<T>::sig_lock = PTHREAD_MUTEX_INITIALIZER;
